/**
 * 1.init serial driver
 */
#include "zephyr/sys/printk.h"
#include <sys/_stdint.h>
#include <uart_async_adapter.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/kernel.h>
#include <zephyr/types.h>

#include <zephyr/logging/log.h>

#include "serial.h"

LOG_MODULE_REGISTER(serial, LOG_LEVEL_INF);

#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
#define UART_WAIT_FOR_RX 5000

#define MAX_PACKET_SIZE 1024 // 串口接收数据的处理buffer
#define PACKET_TIMEOUT_MS 1000
#define CHECK_INTERVAL_MS 100
// #define UART_MSG_BUF_SIZE UART_RX_BUF_SIZE // 接收消息队列缓存大小

#define UART_MSGQ_BLOCK_SIZE (sizeof(struct uart_rx_buf))
#define UART_MSGQ_BLOCK_COUNT 5
#define UART_MSGQ_ALIGNMENT 1

#define UART_SLAB_BLOCK_SIZE (sizeof(struct uart_tx_buf)) // 每块的大小
#define UART_SLAB_BLOCK_COUNT 10
#define UART_SLAB_ALIGNMENT 4

K_MEM_SLAB_DEFINE(uart_tx_slab, UART_SLAB_BLOCK_SIZE, UART_SLAB_BLOCK_COUNT, UART_SLAB_ALIGNMENT); // 定义内存池
K_MSGQ_DEFINE(uart_rx_msgq, UART_MSGQ_BLOCK_SIZE, UART_MSGQ_BLOCK_COUNT, UART_MSGQ_ALIGNMENT);

static K_FIFO_DEFINE(uart_tx_fifo);
static K_FIFO_DEFINE(uart_rx_fifo);

struct uart_rx_buf
{
    uint8_t data[UART_RX_BUF_SIZE];
    size_t len;
};

struct uart_tx_buf
{
    uint8_t data[UART_TX_BUF_SIZE];
    uint16_t len;
};

static struct k_timer check_timer;
static struct k_sem uart_sem;

static uint8_t rx_buf[2][UART_RX_BUF_SIZE];  // 双缓冲
static uint8_t *rx_buf_active = rx_buf[0];   // 活动缓冲
static uint8_t *rx_buf_inactive = rx_buf[1]; // 非活动缓冲

static uint8_t uart_rx_buffer[MAX_PACKET_SIZE]; // 串口接收数据处理的buffer
static size_t uart_rx_buffer_pos = 0;
static int64_t last_receive_time = 0;

static struct serial_inst m_serial_inst = {0};
static rx_proccess_t m_rx_proccess = NULL;

K_THREAD_STACK_DEFINE(uart_thread_stack, 1024);
struct k_thread uart_thread_data;

static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart));
static struct k_work_delayable uart_work;

static void check_timeout(struct k_timer *timer_id)
{
    // 定时器超时，唤醒处理线程
    k_sem_give(&uart_sem);
}

static void uart_cb(const struct device *dev, struct uart_event *evt,
                    void *user_data)
{
    ARG_UNUSED(dev);

    static uint8_t *aborted_buf = NULL;
    static size_t aborted_len = 0;
    struct uart_tx_buf *tx_buf;
    struct uart_rx_buf *rx_buf;

    switch (evt->type)
    {
        case UART_TX_DONE:
            {
                LOG_DBG("UART_TX_DONE");
                // 检查发送完成的事件
                if ((evt->data.tx.len == 0) || (evt->data.tx.buf == 0))
                {
                    return;
                }

                // 获取发送缓冲区
                tx_buf = aborted_buf ? CONTAINER_OF(aborted_buf, struct uart_tx_buf, data[0])
                                     : CONTAINER_OF(evt->data.tx.buf, struct uart_tx_buf, data[0]);

                // 清除已中止的缓冲区
                if (aborted_buf)
                {
                    aborted_buf = NULL;
                    aborted_len = 0;
                }

                // 释放内存池中的缓冲区
                k_mem_slab_free(&uart_tx_slab, (void *)tx_buf);

                // 尝试从FIFO中获取下一个要发送的缓冲区
                tx_buf = k_fifo_get(&uart_tx_fifo, K_NO_WAIT);
                if (!tx_buf)
                {
                    return;
                }

                // 发送下一个缓冲区
                if (uart_tx(uart, tx_buf->data, tx_buf->len, SYS_FOREVER_MS))
                {
                    LOG_WRN("Failed to send data over UART");
                }
            }
            break;

        case UART_RX_RDY:
            {
                // for (size_t i = 0; i < evt->data.rx.len; i += UART_RX_BUF_SIZE)
                // {
                //     size_t chunk_len = MIN(UART_RX_BUF_SIZE, evt->data.rx.len - i);
                //     memcpy(rx_buf.data, &evt->data.rx.buf[i], chunk_len);
                //     rx_buf.len = chunk_len;

                //     if (k_msgq_put(&uart_rx_msgq, &rx_buf, K_NO_WAIT) != 0)
                //     {
                //         printk("UART message queue overflow\n");
                //     }
                //     k_sem_give(&uart_sem);
                // }
                rx_buf = CONTAINER_OF(evt->data.rx.buf, struct uart_rx_buf, data[0]);
                rx_buf->len = evt->data.rx.len;
                if (k_msgq_put(&uart_rx_msgq, &rx_buf, K_NO_WAIT) != 0)
                {
                    printk("UART message queue overflow\n");
                }
                k_sem_give(&uart_sem);
            }
            break;

        case UART_RX_DISABLED:
            {
                LOG_DBG("UART_RX_DISABLED");
                uart_rx_enable(uart, rx_buf_active, UART_RX_BUF_SIZE, UART_WAIT_FOR_RX);
            }
            break;

        case UART_RX_BUF_REQUEST:
            {
                LOG_DBG("UART_RX_BUF_REQUEST");
                uart_rx_buf_rsp(uart, rx_buf_inactive, UART_RX_BUF_SIZE);
            }
            break;

        case UART_RX_BUF_RELEASED:
            {
                LOG_DBG("UART_RX_BUF_RELEASED");
                // 交换分区
                uint8_t *temp = rx_buf_active;
                rx_buf_active = rx_buf_inactive;
                rx_buf_inactive = temp;
            }
            break;

        case UART_TX_ABORTED:
            {
                LOG_DBG("UART_TX_ABORTED");
                if (!aborted_buf)
                {
                    aborted_buf = (uint8_t *)evt->data.tx.buf;
                }

                aborted_len += evt->data.tx.len;
                tx_buf = CONTAINER_OF(aborted_buf, struct uart_tx_buf, data[0]);

                uart_tx(uart, &tx_buf->data[aborted_len], tx_buf->len - aborted_len, SYS_FOREVER_MS);
            }
            break;

        default:
            break;
    }
}

// static void uart_work_handler(struct k_work *item)
// {
//     struct uart_ *buf;

//     // buf = k_malloc(sizeof(*buf));
//     buf = k_mem_pool_alloc(&ser_mem_pool, K_NO_WAIT);
//     if (buf)
//     {
//         buf->len = 0;
//     }
//     else
//     {
//         LOG_WRN("Not able to allocate UART receive buffer");
//         k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
//         return;
//     }

//     uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_WAIT_FOR_RX);
// }

/**
 * 接收串口数据处理
 */
static void uart_thread(void *p1, void *p2, void *p3)
{
    while (1)
    {
        k_sem_take(&uart_sem, K_FOREVER);

        struct uart_rx_buf buf;
        while (k_msgq_get(&uart_rx_msgq, &buf, K_NO_WAIT) == 0)
        {
            for (size_t i = 0; i < buf.len; i++)
            {
                uart_rx_buffer[uart_rx_buffer_pos++] = buf.data[i];
                last_receive_time = k_uptime_get();

                // 数据处理
                if (m_rx_proccess && (m_rx_proccess(uart_rx_buffer, uart_rx_buffer_pos) == 0))
                {
                    // 重置缓冲区位置
                    uart_rx_buffer_pos = 0;
                }

                // 检查是否超出缓冲区
                if (uart_rx_buffer_pos >= sizeof(uart_rx_buffer))
                {
                    printk("UART buffer overflow\n");
                    uart_rx_buffer_pos = 0;
                }
            }
        }

        // 检查超时
        if (k_uptime_get() - last_receive_time > PACKET_TIMEOUT_MS)
        {
            if (uart_rx_buffer_pos > 0)
            {
                printk("Packet reception timeout, resetting buffer\n");
                uart_rx_buffer_pos = 0;
            }
        }
    }
}

/**
 * @brief 串口发送数据
 *
 * @param data 待发送数据
 * @param len 数据长度
 * @return int 发送长度
 */
static int serial_tx(const uint8_t *const data, uint16_t len)
{
    int err;

    // 分片发送
    for (uint16_t pos = 0; pos < len;)
    {
        // 从内存池中分配内存
        struct uart_tx_buf *tx_buf;
        err = k_mem_slab_alloc(&uart_tx_slab, (void **)&tx_buf, K_NO_WAIT);
        if (err)
        {
            LOG_HEXDUMP_ERR(data, len, "serial txs");
            return -ENOMEM;
        }

        // 计算待发送数据的长度
        size_t remaining_len = len - pos;
        tx_buf->len = (remaining_len > sizeof(tx_buf->data)) ? sizeof(tx_buf->data) : remaining_len;

        // 复制数据到缓冲区
        memcpy(tx_buf->data, &data[pos], tx_buf->len);
        pos += tx_buf->len;

        // 尝试发送数据
        err = uart_tx(uart, tx_buf->data, tx_buf->len, SYS_FOREVER_MS);
        if (err)
        {
            // 存储到FIFO中以便后续发送
            k_fifo_put(&uart_tx_fifo, tx_buf);
        }
    }

    return len;
}

struct serial_inst *serial_init(rx_proccess_t rx_proccess_func)
{
    int err;

    k_sem_init(&uart_sem, 0, 1);
    k_timer_init(&check_timer, check_timeout, NULL);
    k_timer_start(&check_timer, K_MSEC(CHECK_INTERVAL_MS),
                  K_MSEC(CHECK_INTERVAL_MS));

    if (!device_is_ready(uart))
    {
        return NULL;
    }

    err = uart_callback_set(uart, uart_cb, NULL);
    if (err)
    {
        LOG_ERR("Cannot initialize UART callback (err: %d)", err);
        return NULL;
    }

    err = uart_rx_enable(uart, rx_buf_active, UART_RX_BUF_SIZE, UART_WAIT_FOR_RX);
    if (err)
    {
        LOG_ERR("Cannot enable uart reception (err: %d)", err);
        return NULL;
    }

    m_serial_inst.tx = serial_tx;
    m_rx_proccess = rx_proccess_func;

    // 消息处理线程
    k_thread_create(&uart_thread_data, uart_thread_stack,
                    K_THREAD_STACK_SIZEOF(uart_thread_stack), uart_thread, NULL,
                    NULL, NULL, 5, 0, K_NO_WAIT);

    LOG_INF("Serial init success.");

    return &m_serial_inst;
}
